﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Antioch.Base.PlayerStates
{
    public class StateMachine
    {
        internal class _Settings
        {
            internal float JumpForce;
            internal float RunForce;
            internal float HorizontalAirControl;
        }

        internal class _Input
        {
            internal bool JumpPressed;
            internal bool UsePressed;
            internal bool FirePressed;
            internal Vector2 NavigationStick;
            internal Vector2 WorldAimStick;
            internal Vector2 RawAimStick;
            internal bool Hurt;
            internal Vector2 MouseAim;
        }

        internal class _Memory
        {
            internal LedgeHangPoint LedgeHangPoint = null;
            internal Box2D.XNA.Joint LedgeHangJoint = null;
            internal int InvulnerableTime = 0;
            internal PushPullGrabPoint PushPullPoint = null;
        }

        internal class _Output
        {
            internal bool CanFire;
        }

        internal _Settings Settings = new _Settings();
        internal _Input Input = new _Input();
        internal _Memory Memory = new _Memory();
        internal _Output Output = new _Output();

        private IState _current = null;
        internal IState CurrentState 
        {
            get
            {
                return _current;
            }

            private set
            {
                if (Object.ReferenceEquals(_current, value)) return;
                if (_current != null) _current.Leave(this);
                if (value != null) value.Enter(this);
                _current = value;
                TimeInState = 0;
            }
        }

        public int TimeInState { get; private set; }

        private Dictionary<System.Type, IState> StateDirectory = new Dictionary<System.Type, IState>();

        internal void Transition(System.Type _stateType)
        {
            if (StateDirectory.ContainsKey(_stateType))
                CurrentState = StateDirectory[_stateType];
            else
            {
                IState newState = Activator.CreateInstance(_stateType) as IState;
                if (newState == null) throw new InvalidProgramException("State type does not implement IState.");
                StateDirectory.Add(_stateType, newState);
                CurrentState = newState;
            }
        }

        public void Update()
        {
            Output.CanFire = true;

            TimeInState += 1;
            Memory.InvulnerableTime -= 1;
            if (Memory.InvulnerableTime == 0)
                PlayerEntity.GetComponent<Health>().Vulnerable = true;

            if (CurrentState != null) CurrentState.Update(this);
        }

        internal Jemgine.Data.EntityRecord PlayerEntity;
        internal Jemgine.Engine.ActorPhysics PhysicsComponent;
        internal Jemgine.Engine.AnimatedSkeleton DrawComponent;
        internal PlayerNavigationModule NavigationModule;
        internal Jemgine.Engine.PhysicsModule PhysicsModule;
        internal PlayerController Controller;


    }
}
